#include "assert_helper.h"
#include "charset_convert.h"

namespace utility {

/*
 * 目标缓冲dst为null时返回转换后的字符个数（不含结束符'\0'）
 * 函数会处理结束符，即会自动加上结束符
 * */
size_t
UTF_8ToUnicode(TCHAR * dst, size_t dst_size/*bytes*/, const char * src)
{
	IF_NULL_RETURN_VALUE(src, CONVERT_ERROR);
	dst_size -= dst_size & 1 ? 1 : 0; // little-entain unicode 所占空间为2的倍数
	int c = 0;
	size_t	real_size = 0;
	size_t	len = 0;

	while (*src) {
		if (NULL == dst || real_size * sizeof(TCHAR) + sizeof(TCHAR) < dst_size) {
			c = 7;
			while (*src & (1 << c)) --c;
			switch (7 - c) {
				case 0:
					if (NULL != dst) {
						dst[real_size++] = *src++;
					} else {
						++src;
					}
				break;
				case 2:
					src += 2;
				break;
				case 3:
					if (NULL != dst) {
						dst[real_size]	= (src[0] & 0x1F) << 12;
						dst[real_size]	|= (src[1] & 0x3F) << 6;
						dst[real_size++] |= (src[2] & 0x3F);
					}
					src += 3;
				break;
				default:
					assert(false);
				break;
			}
		} else {
			break;
		}
		++len;
	}
	if (NULL != dst) dst[real_size] = 0; // handle end of string
	return len;
}

/*
 * 目标缓冲dst为null时返回转换后的字符个数
 * */
size_t/*characters*/
UnicodeToUTF_8(char* dst, size_t dst_size/* in bytes */, const TCHAR * src, size_t src_len/* in chars */)
{
    // 注意 WCHAR高低字的顺序,低字节在前，高字节在后
	IF_NULL_RETURN_VALUE(src, CONVERT_ERROR);

	size_t	len = 0;
	size_t	real_size = 0;
	while (*src) {
		if (NULL != dst) {
			if (real_size + 3 < dst_size) {
				if (0 == *(reinterpret_cast<const char *>(src) + 1)) {	// ASCII compatible utf-8
					dst[real_size++] = *(reinterpret_cast<const char *>(src));
				} else if (*((unsigned int *)src) < 2048) { // 2 bytes utf-8
					dst[real_size++] = (0xC0 | (*src >> 6));
					dst[real_size++] = (0x80 | (*src & 0x3F));
				} else { // 3 bytes utf-8
					dst[real_size++] = (0xE0 | (*src >> 12));
					dst[real_size++] = (0x80 | ((*src >> 6) & 0x3F));
					dst[real_size++] = (0x80 | (*src & 0x3F));
				}
			} else {
				break;
			}
		}
		++len;
		if (src_len > 0 && len >= src_len) break;
		++src;
	}
	if (NULL != dst) dst[real_size] = '\0';
	return len;
}

void UnicodeToGB2312(char* pOut,TCHAR uData)
{
    //::WideCharToMultiByte(CP_ACP,NULL,&uData,1,pOut,sizeof(TCHAR),NULL,NULL);
    return;
}

void Gb2312ToUnicode(TCHAR* pOut,char *gbBuffer)
{
    //::MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,gbBuffer,2,pOut,1);
    return ;
}

void GB2312ToUTF_8(std::string & pOut,char *pText, int pLen)
{
/*    char buf[4];
    int nLength = pLen* 3;
    char* rst = new char[nLength];

    memset(buf,0,4);
    memset(rst,0,nLength);

    int i = 0;
    int j = 0;
    while(i < pLen)
    {
            //如果是英文直接复制就可以
            if( *(pText + i) >= 0)
            {
                    rst[j++] = pText[i++];
            }
            else
            {
                    TCHAR pbuffer;
                    Gb2312ToUnicode(&pbuffer,pText+i);

                    UnicodeToUTF_8(buf,&pbuffer);

                    unsigned short int tmp = 0;
                    tmp = rst[j] = buf[0];
                    tmp = rst[j+1] = buf[1];
                    tmp = rst[j+2] = buf[2];

                    j += 3;
                    i += 2;
            }
    }
    rst[j] = '\0';

    //返回结果
    pOut = rst;
    delete []rst;

    return;*/
}

void UTF_8ToGB2312(std::string & pOut, char *pText, int pLen)
{
/*    char * newBuf = new char[pLen];
    char Ctemp[4];
    memset(Ctemp,0,4);

    int i =0;
    int j = 0;

    while(i < pLen)
    {
        if(pText > 0)
        {
                newBuf[j++] = pText[i++];
        }
        else
        {
                TCHAR Wtemp;
                UTF_8ToUnicode(&Wtemp,pText + i);

                UnicodeToGB2312(Ctemp,Wtemp);

                newBuf[j] = Ctemp[0];
                newBuf[j + 1] = Ctemp[1];

                i += 3;
                j += 2;
        }
    }
    newBuf[j] = '\0';

    pOut = newBuf;
    delete []newBuf;

    return;*/
}

bool is_UCS_2_string(const char * str, size_t len)
{
	IF_NULL_RETURN_VALUE(str, false);
	if (len > 1 && 0 == (len & 1)) { // Length of UCS-2 string must be even number
		for (size_t i = 0; i < 2; ++i) {
			if (str[i] <= 0) return true;
		}
	}
	return false;
}

bool is_UTF_8_string(const char * str, size_t len)
{
	IF_NULL_RETURN_VALUE(str, false);

	size_t nBytes = 0;//UFT8可用1-6个字节编码,ASCII用一个字节
	unsigned char chr;
	bool bAllAscii = true; //如果全部都是ASCII, 说明不是UTF-8
	for(size_t i = 0; i < len; ++i) {
		chr = *(str+i);
		if( (chr&0x80) != 0 ) // 判断是否ASCII编码,如果不是,说明有可能是UTF-8,ASCII用7位编码,但用一个字节存,最高位标记为0,o0xxxxxxx
		bAllAscii = false;
		if(nBytes == 0) {//如果不是ASCII码,应该是多字节符,计算字节数
			if(chr >= 0x80) {
				if (chr>=0xFC && chr<=0xFD) nBytes = 6;
				else if (chr >= 0xF8) nBytes = 5;
				else if (chr >= 0xF0) nBytes = 4;
				else if (chr >= 0xE0) nBytes = 3;
				else if (chr >= 0xC0) nBytes = 2;
				else return false;
				--nBytes;
			}
		} else { //多字节符的非首字节,应为 10xxxxxx
			if( (chr & 0xC0) != 0x80 ) return false;
			--nBytes;
		}
	}
	if(nBytes > 0) return false; //违返编码规则
	if(bAllAscii)  return false; //如果全部都是ASCII, 说明不是UTF-8
	return true;
}
}
